package com.blustreaksw.cyclecoach;

import java.util.ArrayList;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

import com.blustreaksw.cyclecoach.btle.BtleDeviceType;
import com.blustreaksw.cyclecoach.data.UserProfile;
import com.blustreaksw.cyclecoach.data.UserProfile.MeasurementUnits;
import com.blustreaksw.cyclecoach.data.WorkoutDatabaseHelper;
import com.blustreaksw.cyclecoach.history.WorkoutHistoryContainer;
import com.blustreaksw.cyclecoach.history.WorkoutLogEntryFragment;
import com.blustreaksw.cyclecoach.main.Fragment_CentralNavigation;
import com.blustreaksw.cyclecoach.service.CycleCoachService;

public class MainActivity extends UserProfileActivity {
	private static final String TAG = "MainActivity";
	public static final String FRAGMENT_CENTRAL_CONTROL = "centralControl";
	public static final String FRAGMENT_ACTIVE_WORKOUT = "activeWorkout";
	public static final String FRAGMENT_WORKOUT_SUMMARY = "workoutSummary";
	
	public static final String SP_PERSISTENT_INFO = "mainActivity_sharedPreferences";
	public static final String SP_ACTIVE_USER = "mainActivity_activeUser";
	public static final String SP_ACTIVE_WORKOUT = "mainActivity_activeWorkout";
	
	/***********************************************************************
     * Key for specifying the numeric ID of the user that we need to pull
     * from the database.
     ***********************************************************************/
	public static final String EXTRA_USER_ID = 
			MainActivity.class.getPackage().getName() + ".extra_user_id";
	
	
	private long mUserId;
	private ArrayList<BtleDeviceTracker> mDevices;
	private int connectIterator;
	private boolean shutdownInProgress = false;
	private boolean mTransitionActiveWorkoutToSummary = false;
	private WorkoutHistoryContainer mWorkoutContainer;
	private int mCentralControl_startView_listPosition;
	private boolean mHrmConnected = false;
	private boolean mCscConnected = false;
	private boolean mPowerConnected = false;
	
	public void setCentralNavigationStartViewPosition(int listPosition) {
		mCentralControl_startView_listPosition = listPosition;
	}
	
	public int getCentralNavigationStartViewPosition() {
		return mCentralControl_startView_listPosition;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getActionBar().setTitle("CycleCoach");
		setUsedForWizard(false);
		
		mCentralControl_startView_listPosition = 0;
		
		mDevices = new ArrayList<BtleDeviceTracker>();
		
		Bundle bundle = getIntent().getExtras();
		if(bundle != null) {
			mUserId = bundle.getLong(EXTRA_USER_ID, -1);
			WorkoutDatabaseHelper.getInstance(getApplicationContext()).setCurrentUser(getApplicationContext(), mUserId);
		} else {
			mUserId = -1;
		}
		
		
		if(mUserId < 0) {
			mUserId = WorkoutDatabaseHelper.getInstance(getApplicationContext()).getLastUser(getApplicationContext());
		}
		
		// Load user information into UserProfile object
		mUserProfile.loadUserFromDb(mUserId);
		getActionBar().setSubtitle("User: " + mUserProfile.getUserName());
		
		if(findViewById(R.id.fragmentContainer) != null) {
			
			if(savedInstanceState != null) {
				return;
			}

			Fragment fragment;
		
			if((fragment = getSupportFragmentManager().
						findFragmentByTag(FRAGMENT_CENTRAL_CONTROL)) == null) {
					fragment = new Fragment_CentralNavigation();
			}
			
			getSupportFragmentManager().beginTransaction()
				.add(R.id.fragmentContainer, fragment).commit();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.menu_main, menu);
		return true;
	}
	
	@Override
	public void onPause() {
		
		
		// Save the current userId
		SharedPreferences sp = getSharedPreferences(SP_PERSISTENT_INFO, MODE_PRIVATE);
		SharedPreferences.Editor editor = sp.edit();
		editor.putLong(SP_ACTIVE_USER, mUserId);
		editor.commit();
		
		doUnbindService();
		super.onPause();
	}
	
	@Override
	public void onResume() {
		
		
		if(mUserProfile == null) {
			SharedPreferences sp = getSharedPreferences(SP_PERSISTENT_INFO, MODE_PRIVATE);
			mUserId = sp.getLong(SP_ACTIVE_USER, -1);
			
			mUserProfile = UserProfile.getInstance(getApplicationContext());
			mUserProfile.loadUserFromDb(mUserId);
		}
		
		// Grab the container of workout histories now to establish the context.
		mWorkoutContainer = WorkoutHistoryContainer.getInstance(this);
		WorkoutHistoryContainer.setMeasurementUnits(mUserProfile.getDisplayUnits().equals(MeasurementUnits.METRIC));
		mWorkoutContainer.changeUserId(mUserId);
		
		// Startup the CycleCoach service so we can connect to paired devices
		doBindService();
		
		super.onResume();
		
	}
	
	@Override
    public void onBackPressed() {
    	Log.d(TAG, "onBackPressed()");
    	if(mTransitionActiveWorkoutToSummary) {
    		// Ignore button press.
    	} else if(isWorkoutActive()) {
    		// TODO
    		// Display message to confirm stopping workout session.
    	} else {
    		super.onBackPressed();
    	}
    }
	
	public boolean isWorkoutActive() {
		return WorkoutDatabaseHelper
				.getInstance(getApplicationContext())
				.isWorkoutActive(getApplicationContext());
	}
	
	public boolean isWorkoutPaused() {
		return WorkoutDatabaseHelper
				.getInstance(getApplicationContext())
				.isWorkoutPaused(getApplicationContext());
	}
	
	private void onRegistrationAccepted() {
		Log.d(TAG, "(onRegistrationAccepted) Registered with CycleCoach service.");
		mDevices = new ArrayList<BtleDeviceTracker>();
		
		if(mUserProfile.getHeartRateMonitorAddress().equals("") == false) {
			mDevices.add(new BtleDeviceTracker(mUserProfile.getHeartRateMonitorAddress(),
					BtleDeviceType.HEART_RATE_MONITOR));			
		} else {
			Log.d(TAG, "No HRM device paired.");
		}
		
		if(mUserProfile.getCyclingSpeedCadenceSensorAddress().equals("") == false) {
			mDevices.add(new BtleDeviceTracker(mUserProfile.getCyclingSpeedCadenceSensorAddress(),
					BtleDeviceType.CYCLING_SPEED_CADENCE_SENSOR));
			
		} else {
			Log.d(TAG, "No CSC device paired.");
		}
		
		if(mUserProfile.getCyclingPowerMeterAddress().equals("") == false) {
			mDevices.add(new BtleDeviceTracker(mUserProfile.getCyclingPowerMeterAddress(),
					BtleDeviceType.CYCLING_POWER_METER));
			
		} else {
			Log.d(TAG, "No POWER device paired.");
		}
		
		connectNextDevice();
		connectIterator = 0;
	}
	
	public void connectDevice(String address, BtleDeviceType type) {
		Bundle bundle = new Bundle();
		bundle.putString(CycleCoachService.EXTRA_BTLE_ADDRESS, address);
		bundle.putInt(CycleCoachService.EXTRA_BTLE_TYPE, type.getValue());
		sendMsgToService(CycleCoachService.MSG_CONNECT_BTLE_DEVICE, 0, 0, bundle);
	}
	
	public void disconnectDevice(String address) {
		BtleDeviceTracker tracker = findTracker(address);
		
		if(tracker != null) {
			mDevices.remove(tracker);
			Bundle bundle = new Bundle();
			bundle.putString(CycleCoachService.EXTRA_BTLE_ADDRESS, tracker.mAddress);
			sendMsgToService(CycleCoachService.MSG_DISCONNECT_BTLE_DEVICE, 0, 0, bundle);
		}
	}
	
	public void newDeviceAdded(BtleDeviceType type, String address) {
		
		BtleDeviceTracker tracker = new BtleDeviceTracker(address, type);
		mDevices.add(0, tracker);
		Bundle bundle = new Bundle();
		bundle.putString(CycleCoachService.EXTRA_BTLE_ADDRESS, tracker.mAddress);
		bundle.putInt(CycleCoachService.EXTRA_BTLE_TYPE, tracker.mType.getValue());
		sendMsgToService(CycleCoachService.MSG_CONNECT_BTLE_DEVICE, 0, 0, bundle);
		return;
	}
	
	private void connectNextDevice() {
		
		if(shutdownInProgress) {
			Log.d(TAG, "Shutdown in progress");
			return;
		}
		
		BtleDeviceTracker tracker;
		int count = mDevices.size();
		Log.d(TAG, "(connectNextDevice) start.");
		
		if(mDevices.isEmpty()) return;
			
		while((tracker = mDevices.get(connectIterator)).mIsConnected == true) {
			connectIterator = (connectIterator + 1) % mDevices.size();
			if(--count == 0) {
				Log.d(TAG, "All devices connected.");
				return;
			}
		}
		
		connectIterator = (connectIterator + 1) % mDevices.size();
		connectDevice(tracker.mAddress, tracker.mType);
		return;
	}
	
	private boolean sendMsgToService(int command, int arg1, int arg2, Bundle bundle) {
		try {
			if(mService != null) {
				Message msg = Message.obtain(null, command, arg1, arg2);
				if(bundle != null) {
					msg.setData(bundle);
				}
				mService.send(msg);
				return true;
			}
		} catch (RemoteException e) {
			serviceConnectionLost();
			return false;
		}
		
		return false;
	}
	
	public void serviceConnectionLost() {
		// TODO
	}
	
	
	private class BtleDeviceTracker {
		boolean mIsConnected;
		String mAddress;
		BtleDeviceType mType;
		
		BtleDeviceTracker(String addr, BtleDeviceType type) {
			mAddress = addr;
			mType = type;
			mIsConnected = false;
		}
	}
	
	private BtleDeviceTracker findTracker(String address) {
		for(BtleDeviceTracker a: mDevices) {
			if(a.mAddress.equals(address)) return a;
		}
		
		return null;
	}
	
	
	/***********************************************************************
	 ***********************************************************************
     * CycleCoach service communication protocols
     ***********************************************************************
     ***********************************************************************/
	
	/** Messenger for communicating with service. */
	Messenger mService = null;
	
	/** Flag indicating whether we have called bind on the service. */
	boolean mIsBound;
	
	class IncomingHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			Bundle data = (Bundle) msg.getData();
			Bundle bundle = new Bundle();
			String address;
			BtleDeviceTracker tracker;
			Log.d(TAG, "(Activity - handleMessage) " + msg.what);
			switch(msg.what) {
				case CycleCoachService.MSG_REGISTRATION_ACCEPTED:
					onRegistrationAccepted();
					break;
				case CycleCoachService.MSG_REGISTRATION_DENIED:
					Log.d(TAG, "Server refused connection request.");
					// Detach our existing connection.
			        unbindService(mConnection);
			        mIsBound = false;
			        Toast.makeText(MainActivity.this, "CycleCoach service refused connection.",
			                Toast.LENGTH_SHORT).show();
					break;
					
				case CycleCoachService.MSG_DEREGISTER_ACK:
					Log.d(TAG, "No longer registered with CycleCoach server process.");
					// Detach our existing connection.
			        unbindService(mConnection);
			        mIsBound = false;
			        Toast.makeText(MainActivity.this, "Unbinding CycleCoach service",
			                Toast.LENGTH_SHORT).show();
					break;
					
				case CycleCoachService.MSG_BTLE_CONNECT_SUCCESS:
					address = data.getString(CycleCoachService.EXTRA_BTLE_ADDRESS, null);
					tracker = findTracker(address);
					
					if(tracker == null) {
						Log.d(TAG, "(handleMessage) findTracker() returned null.");
						return;
					}
					
					String devName = data.getString(CycleCoachService.EXTRA_BTLE_DEVICE_NAME);
					
					Toast.makeText(MainActivity.this,
							String.format("Connected %s", devName),
			                Toast.LENGTH_SHORT).show();
					
					handleDeviceStatusUpdate_viewIndicator(tracker.mType, true);
					
					if(tracker.mType == BtleDeviceType.HEART_RATE_MONITOR) {
						bundle.putString(CycleCoachService.EXTRA_BTLE_ADDRESS, tracker.mAddress);
						bundle.putInt(CycleCoachService.EXTRA_BTLE_TYPE, tracker.mType.getValue());
						
					} else if(tracker.mType == BtleDeviceType.CYCLING_SPEED_CADENCE_SENSOR) {
						bundle.putString(CycleCoachService.EXTRA_BTLE_ADDRESS, tracker.mAddress);
						bundle.putInt(CycleCoachService.EXTRA_BTLE_TYPE, tracker.mType.getValue());
						bundle.putDouble(CycleCoachService.EXTRA_WHEEL_CIRCUMFERENCE, 2.096);
					}
					
					sendMsgToService(CycleCoachService.MSG_BTLE_START_CLIENT_DATA_UPDATES, 0, 0, bundle);
					
					Log.d(TAG, String.format("BtleDevice %s connected", address));
					tracker.mIsConnected = true;
					connectNextDevice();
					break;
					
				case CycleCoachService.MSG_BTLE_CONNECT_FAILED:
					address = data.getString(CycleCoachService.EXTRA_BTLE_ADDRESS, "Unknown device");
					tracker = findTracker(address);
					if(tracker != null) {
						handleDeviceStatusUpdate_viewIndicator(tracker.mType, true);
					}
					Log.d(TAG, String.format("BtleDevice %s connection error: %s", address,
							data.getString(CycleCoachService.EXTRA_BTLE_ERROR_STRING, "Unknown error")));
					connectNextDevice();
					
					break;
					
				case CycleCoachService.MSG_BTLE_CONNECTION_DROPPED:
					address = data.getString(CycleCoachService.EXTRA_BTLE_ADDRESS, "Unknown device");
					tracker = findTracker(address);
					if(tracker != null) {
						handleDeviceStatusUpdate_viewIndicator(tracker.mType, true);
					}
					Log.d(TAG, String.format("BtleDevice %s connection error: %s", address,
							data.getString(CycleCoachService.EXTRA_BTLE_ERROR_STRING, "Unknown error")));
					break;
					
				case CycleCoachService.MSG_BTLE_DATA_UPDATE:
					address = data.getString(CycleCoachService.EXTRA_BTLE_ADDRESS, null);
					tracker = findTracker(address);
					Log.d(TAG, "MSG_BTLE_DATA_UPDATE: " + tracker.mType.toString() + " " + address);
					handleDataUpdateFromService(tracker.mType, data);
					break;
					
				case CycleCoachService.MSG_BTLE_DEVICE_START_SESSION_ACK:
					break;
				case CycleCoachService.MSG_BTLE_DEVICE_STOP_SESSION_ACK:
					openSummaryActivity(msg.arg1);
					break;
				case CycleCoachService.MSG_BTLE_DEVICE_PAUSE_SESSION_ACK:
					break;
				case CycleCoachService.MSG_BTLE_DEVICE_RESUME_SESSION_ACK:
					break;
				case CycleCoachService.MSG_BTLE_DEVICE_INCREMENT_LAP_SESSION_ACK:
					break;
				case CycleCoachService.MSG_BTLE_DEVICE_NOT_FOUND:
					break;
					
				case CycleCoachService.MSG_DISPLAY_TIME_UPDATE:
					if(mUpdateActiveWorkoutScreenDataCallback != null) {
						mUpdateActiveWorkoutScreenDataCallback.updateTimeField(data.getInt(CycleCoachService.EXTRA_TIME_ELAPSED, 0));
					}
				default:
					break;
			}
		}
	}
	
	private void openSummaryActivity(int sessionId) {
		Bundle bundle = new Bundle();
		bundle.putInt(CycleCoachService.EXTRA_SESSION_ID, sessionId);
		
		Fragment fragment;
		if((fragment = getSupportFragmentManager().
				findFragmentByTag(MainActivity.FRAGMENT_WORKOUT_SUMMARY)) == null) {
			fragment = new WorkoutLogEntryFragment();
		}
	
		fragment.setArguments(bundle);
		mTransitionActiveWorkoutToSummary = false;
		getSupportFragmentManager().beginTransaction()
			.replace(R.id.fragmentContainer, fragment, MainActivity.FRAGMENT_CENTRAL_CONTROL)
			.addToBackStack(null)
			.commit();
	}
	
	/**
	 * Target we publish for clients to send messages to IncomingHandler.
	 */
	final Messenger mMessenger = new Messenger(new IncomingHandler());
	
	/**
	 * Class for interacting with the main interface of the service.
	 */
	private ServiceConnection mConnection = new ServiceConnection() {
	    public void onServiceConnected(ComponentName className,
	            IBinder service) {
	        // This is called when the connection with the service has been
	        // established, giving us the service object we can use to
	        // interact with the service.  We are communicating with our
	        // service through an IDL interface, so get a client-side
	        // representation of that from the raw service object.
	        mService = new Messenger(service);
	        //mCallbackText.setText("Attached.");

	        // We want to monitor the service for as long as we are
	        // connected to it.
	        try {
	            Message msg = Message.obtain(null,
	                    CycleCoachService.MSG_REGISTER_CLIENT);
	            msg.replyTo = mMessenger;
	            mService.send(msg);
	        } catch (RemoteException e) {
	            // In this case the service has crashed before we could even
	            // do anything with it; we can count on soon being
	            // disconnected (and then reconnected if it can be restarted)
	            // so there is no need to do anything here.
	        	Toast.makeText(MainActivity.this, "Unable to connect to CycleCoach service.",
	                    Toast.LENGTH_SHORT).show();
	        }

	        // Inform the user we successfully connected to the service.
	        Toast.makeText(MainActivity.this, "CycleCoach service connected",
	                Toast.LENGTH_SHORT).show();
	    }

	    public void onServiceDisconnected(ComponentName className) {
	        // This is called when the connection with the service has been
	        // unexpectedly disconnected -- that is, its process crashed.
	        mService = null;

	        // As part of the sample, tell the user what happened.
	        Toast.makeText(MainActivity.this, "CycleCoach service disconnected",
	                Toast.LENGTH_SHORT).show();
	    }
	};

	void doBindService() {
		shutdownInProgress = false;
		startService(new Intent(MainActivity.this, CycleCoachService.class));
	    // Establish a connection with the service.
	    bindService(new Intent(MainActivity.this, 
	            CycleCoachService.class), mConnection, Context.BIND_AUTO_CREATE);
	    mIsBound = true;
	}

	void doUnbindService() {
		shutdownInProgress = true;
	    if (mIsBound) {
	        // If we have received the service, and hence registered with
	        // it, then now is the time to unregister.
	        if (mService != null) {
	            try {
	                Message msg = Message.obtain(null,
	                        CycleCoachService.MSG_DEREGISTER_CLIENT);
	                msg.replyTo = mMessenger;
	                mService.send(msg);
	            } catch (RemoteException e) {
	                // There is nothing special we need to do if the service
	                // has crashed.
	            	unbindService(mConnection);
	    	        mIsBound = false;
	    	        Toast.makeText(MainActivity.this, "Unbinding CycleCoach service",
	    	                Toast.LENGTH_SHORT).show();
	            }
	        }
	    }
	}
	
	private void handleDataUpdateFromService(BtleDeviceType type, Bundle data) {
		if(type == BtleDeviceType.HEART_RATE_MONITOR) {
			int bpm = data.getInt(CycleCoachService.EXTRA_HRM_BPM);
			synchronized(mDisplayClientSyncKey) {
				if(mUpdateActiveWorkoutScreenDataCallback != null) {
					mUpdateActiveWorkoutScreenDataCallback.updateHrmField(bpm);
				}
			}

		} else if(type == BtleDeviceType.CYCLING_SPEED_CADENCE_SENSOR) {
			double speed = data.getDouble(CycleCoachService.EXTRA_CSC_SPEED);
			int rpm = data.getInt(CycleCoachService.EXTRA_CSC_CRANK_RPM);
			double distanceTraveled = data.getDouble(CycleCoachService.EXTRA_TOTAL_DISTANCE);
			synchronized(mDisplayClientSyncKey) {
				if(mUpdateActiveWorkoutScreenDataCallback != null) {
					mUpdateActiveWorkoutScreenDataCallback.updateSpeedField(speed);
					mUpdateActiveWorkoutScreenDataCallback.updateCadenceField(rpm);
					mUpdateActiveWorkoutScreenDataCallback.updateDistanceField(distanceTraveled);
				}
			}
		} else if(type == BtleDeviceType.CYCLING_POWER_METER) {
			int watts = data.getInt(CycleCoachService.EXTRA_POWER_WATTS);
			synchronized(mDisplayClientSyncKey) {
				if(mUpdateActiveWorkoutScreenDataCallback != null) {
					mUpdateActiveWorkoutScreenDataCallback.updatePowerField(watts);
				}
			}
		}
	}
	
	private void handleDeviceStatusUpdate_viewIndicator(BtleDeviceType type, boolean connected) {
		if(type.equals(BtleDeviceType.HEART_RATE_MONITOR)) {
			synchronized(mDisplayClientSyncKey)  {
				if(mUpdateCentralNavigationScreenDataCallback != null) {
					mHrmConnected = connected;
					mUpdateCentralNavigationScreenDataCallback.hrmStatusUpdate(connected);
				}
			}
		} else if(type.equals(BtleDeviceType.CYCLING_SPEED_CADENCE_SENSOR)) {
			synchronized(mDisplayClientSyncKey)  {
				if(mUpdateCentralNavigationScreenDataCallback != null) {
					mCscConnected = connected;
					mUpdateCentralNavigationScreenDataCallback.cscStatusUpdate(connected);
				}
			}
		} else if(type.equals(BtleDeviceType.CYCLING_POWER_METER)) {
			synchronized(mDisplayClientSyncKey)  {
				if(mUpdateCentralNavigationScreenDataCallback != null) {
					mPowerConnected = connected;
					mUpdateCentralNavigationScreenDataCallback.powerStatusUpdate(connected);
				}
			}
		}
	}
	
	public void startClientNotifications(UpdateActiveWorkoutScreenDataCallback cb) {
		synchronized(mDisplayClientSyncKey) {
			mUpdateActiveWorkoutScreenDataCallback = cb;
		}
		
		activeWorkoutScreenDisplayed(true);
	}
	
	public void stopClientNotifications() {
		synchronized(mDisplayClientSyncKey) {
			mUpdateActiveWorkoutScreenDataCallback = null;
		}
		
		activeWorkoutScreenDisplayed(false);
	}
	
	public interface UpdateActiveWorkoutScreenDataCallback {
		
		public void updateHrmField(int hrm);
		public void updateCadenceField(int cadence);
		public void updatePowerField(int power);
		public void updateSpeedField(double speed);
		public void updateTimeField(int time);
		public void updateDistanceField(double distance);
	}
	
	public interface UpdateCentralNavigationScreenDataCallback {
		public void hrmStatusUpdate(boolean connected);
		public void cscStatusUpdate(boolean connected);
		public void powerStatusUpdate(boolean connected);
	}
	
	public void registerCentralNavigationCallback(UpdateCentralNavigationScreenDataCallback cb) {
		synchronized(mDisplayClientSyncKey)  {
			mUpdateCentralNavigationScreenDataCallback = cb;
			mUpdateCentralNavigationScreenDataCallback.powerStatusUpdate(mPowerConnected);
			mUpdateCentralNavigationScreenDataCallback.cscStatusUpdate(mCscConnected);
			mUpdateCentralNavigationScreenDataCallback.hrmStatusUpdate(mHrmConnected);
		}
	}
	
	public void deregisterCentralNavigationCallback() {
		synchronized(mDisplayClientSyncKey)  {
			mUpdateCentralNavigationScreenDataCallback = null;
		}
	}
	
	private UpdateActiveWorkoutScreenDataCallback mUpdateActiveWorkoutScreenDataCallback;
	private Object mDisplayClientSyncKey = new Object();
	private UpdateCentralNavigationScreenDataCallback mUpdateCentralNavigationScreenDataCallback;
	
	
	public void startWorkoutSession() {
		int sessionId = WorkoutDatabaseHelper.getInstance(getApplicationContext()).startNewWorkoutSession(getApplicationContext(), mUserId, 2.096);
		Log.d(TAG, "Starting new workout session, sessionId: " + sessionId + ", userId: " + mUserId);
		Bundle bundle = new Bundle();
		bundle.putInt(CycleCoachService.EXTRA_SESSION_ID, sessionId);
		sendMsgToService(CycleCoachService.MSG_BTLE_DEVICE_START_SESSION, 0, 0, bundle);
	}
	
	public void stopWorkoutSession() {
		mTransitionActiveWorkoutToSummary = true;
		sendMsgToService(CycleCoachService.MSG_BTLE_DEVICE_STOP_SESSION, 0, 0, null);
	}
	
	public void pauseWorkoutSession() {
		sendMsgToService(CycleCoachService.MSG_BTLE_DEVICE_PAUSE_SESSION, 0, 0, null);
	}
	
	public void resumeWorkoutSession() {
		Bundle bundle = new Bundle();
		bundle.putInt(CycleCoachService.EXTRA_SESSION_ID, 123);
		sendMsgToService(CycleCoachService.MSG_BTLE_DEVICE_RESUME_SESSION, 0, 0, null);
	}
	
	public void incrementSessionLap() {
		
	}
	
	public void activeWorkoutScreenDisplayed(boolean isDisplayed) {
		if(isDisplayed) {
			sendMsgToService(CycleCoachService.MSG_BTLE_START_CLIENT_DATA_UPDATES, 0, 0, new Bundle());
		} else {
			sendMsgToService(CycleCoachService.MSG_BTLE_STOP_CLIENT_DATA_UPDATES, 0, 0, new Bundle());
		}
	}
}
